import os
import json
import torch
from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as plt
from torch_Beit_model import BEiTImageEncoder


def pred(img_path, json_path = './class_indices.json', model_weight_path = './beit_model/best_model.pth'):
    data_transform = transforms.Compose(
        [transforms.Resize(224),
         transforms.CenterCrop(224),
         transforms.ToTensor(),
         transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])

    # load image
    assert os.path.exists(img_path), "file: '{}' dose not exist.".format(img_path)
    img = Image.open(img_path)
    # img.show()
    img = data_transform(img)
    img = torch.unsqueeze(img, dim = 0)  # [N, C, H, W]

    # read class_indict
    assert os.path.exists(json_path), "file: '{}' dose not exist.".format(json_path)

    with open(json_path, "r") as f:
        class_indict = json.load(f)

    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    # create model
    model = BEiTImageEncoder()
    # load model weights
    assert os.path.exists(model_weight_path), "file: '{}' dose not exist.".format(model_weight_path)
    model.load_state_dict(torch.load(model_weight_path, map_location = device))
    model.eval()
    model.to(device)
    with torch.no_grad():
        # predict class
        output = torch.squeeze(model(img.to(device))).cpu()
        predict = torch.softmax(output, dim = 0)
        predict_cla = torch.argmax(predict).numpy()

    print_res = "class: {}   prob: {:.3}".format(class_indict[str(predict_cla)],
                                                 predict[predict_cla].numpy())
    plt.title(print_res)
    for i in range(len(predict)):
        print("class: {:10}   prob: {:.3}".format(class_indict[str(i)],
                                                  predict[i].numpy()))


if __name__ == '__main__':
    test = r''
    pred(test)
